using System;
using System.Diagnostics;
using System.Windows.Forms;
using Microsoft.WowAddonStudio.Lua.RuntimeService.ShellHost;

namespace Microsoft.WowAddonStudio.Lua.RuntimeService.WowBench
{
	/// <summary>
	/// WoWBenchController class, implements <see cref="IWoWBenchController"/>.
	/// </summary>
	public sealed class WoWBenchController : IWoWBenchController
	{

		#region Private Variables

		private const string CONTROL_BREAK = "%BREAK%";
		private readonly CommandHistory commandHistory;
		private IOutputControl outputControl;

		#endregion

		#region Lifecycle Methods

		/// <summary>
		/// Initializes a new instance of the <see cref="WoWBenchController"/> class.
		/// </summary>
		/// <param name="runtime">The <see cref="LuaRuntime"/> parameter.</param>
		public WoWBenchController(ILuaRuntime runtime)
		{
			if (runtime == null)
				throw new ArgumentNullException("runtime");

			commandHistory = new CommandHistory(this);
			Runtime = runtime;
			WoWBenchPath = runtime.WowBenchPath;
			WowBenchCommand = new WoWBenchCommand(this, string.Empty);
		}

		#endregion

		#region IWoWBenchController Members

		/// <summary>
		/// Gets the IShellHost for current Runtime.
		/// </summary>
		public IShellHost RuntimeShellHost
		{
			get { return Runtime.RuntimeShellHost; }
		}

		/// <summary>
		/// CommandHistory for WoWBench window.
		/// </summary>
		public ICommandHistory CommandHistory
		{
			get { return commandHistory; }
		}

		/// <summary>
		/// Gets the current WoWBenchCommand.
		/// </summary>
		public ICommandEntry WowBenchCommand
		{
			get { return commandHistory.New; }
			private set { commandHistory.New = value; }
		}

		/// <summary>
		/// Gets the IOutputWriter implementation.
		/// </summary>
		public IOutputWriter TextOutputWriter { get; private set; }

		/// <summary>
		/// Gets the current text buffer position.
		/// </summary>
		public int BufferPosition { get; private set; }

		/// <summary>
		/// Resets the controller state.
		/// </summary>
		public void Reset()
		{
			CommandHistory.Clear();
			WowBenchCommand.Clear();
		}

		/// <summary>
		/// Initialize the <see cref="WoWBenchController"/>.
		/// </summary>
		/// <param name="textBox">The display control for <see cref="IOutputWriter"/>.</param>
		public void Initialize(TextBoxBase textBox)
		{
			if (textBox == null)
				throw new ArgumentNullException("textBox");

			textBox.Clear();
			BufferPosition = 0;

			if (TextOutputWriter != null)
				((IEventProvider)TextOutputWriter).UnsubscribeEvents();

			if(outputControl != null)
				outputControl.Dispose();

			outputControl = new RichTextOutputControl(textBox as RichTextBox);

			TextOutputWriter = new WoWBenchOutputWriter(outputControl);
			TextOutputWriter.OnAfterWrite += OutputWriterOnAfterWrite;
			
			CommandHistory.Clear();
		}

		/// <summary>
		/// Gets appended text and its position.
		/// </summary>
		/// <param name="sender">The sender as <see cref="IOutputWriter"/></param>
		/// <param name="e">The event data as <see cref="OutputWriterEventArgs"/></param>
		private void OutputWriterOnAfterWrite(object sender, OutputWriterEventArgs e)
		{
			BufferPosition = e.BufferPosition;
		}

		/// <summary>
		/// Writes the given message to the output.
		/// </summary>
		/// <param name="message">The desired message.</param>
		/// <param name="error">If true then write message as error.</param>
		public void SendMessage(string message, bool error)
		{
			if (!string.IsNullOrEmpty(message))
			{
				if(error)
					TextOutputWriter.WriteErrorText((message));
				else
					TextOutputWriter.WriteLine(message);
			}
		}

		/// <summary>
		/// Executes command in <see cref="IShellHost"/>.
		/// </summary>
		/// <param name="command">The shell command.</param>
		public string ExecuteCommand(string command)
		{
			Debug.WriteLine(String.Concat("Executing command: ", command));

			if (!string.IsNullOrEmpty(command) 
				&& RuntimeShellHost != null && RuntimeShellHost.ShellState != ShellHostState.Closed)
			{
				try
				{
					if (command == CONTROL_BREAK)
					{
						//If CTRL+BREAK pressed then terminate shell host processes
						Trace.WriteLine(RuntimeShellHost.TerminateChildProcess());
					}
					else
					{
						//Execute command into RuntimeShellHost context
						RuntimeShellHost.ExecuteCommand(command);

						//Add new command to the CommandHistory
						commandHistory.Add(new WoWBenchCommand(this, command));

						//Clear prevoius temporary command
						WowBenchCommand.Clear();
					}
				}
				catch (Exception ex)
				{
					Trace.WriteLine(ex);
					throw;
				}
			}
			return command;
		}

		/// <summary>
		/// Run WoWBench in shell process and loads current AddOn.
		/// </summary>
		/// <returns>True if shell process started successfully, otherwise false.</returns>
		public bool RunWoWBenchAddOn()
		{
			return Run(LuaRuntimeType.WoWBenchAddon);
		}

		/// <summary>
		/// Run WoWBench in shell process.
		/// </summary>
		/// <returns>True if shell process started successfully, otherwise false.</returns>
		public bool RunWoWBench()
		{
			return Run(LuaRuntimeType.WoWBench);
		}

		/// <summary>
		/// Run Lua prompt in shell process.
		/// </summary>
		/// <returns>True if shell process started successfully, otherwise false.</returns>
		public bool RunLuaInterpreter()
		{
			return Run(LuaRuntimeType.LuaInterpreter);
		}

		/// <summary>
		/// Run shell process.
		/// </summary>
		/// <returns>True if shell process started successfully, otherwise false.</returns>
		internal bool Run(LuaRuntimeType runtimeType)
		{
			Reset();

            switch (runtimeType)
            {
                case LuaRuntimeType.LuaInterpreter:
                    TextOutputWriter.WriteLine("Starting Lua prompt...");
                    break;
                case LuaRuntimeType.WoWBench:
                case LuaRuntimeType.WoWBenchAddon:
                    TextOutputWriter.WriteLine(Resources.StartWoWBenchMessage);
                    break;
                
            }
			
			return Runtime.Load(runtimeType);
		}


		/// <summary>
		/// Performs application-defined tasks associated with freeing,
		/// releasing, or resetting unmanaged resources.
		/// </summary>
		public void Dispose()
		{
			if (RuntimeShellHost != null) RuntimeShellHost.Dispose();
			if (commandHistory != null) commandHistory.Dispose();
			if (outputControl != null) outputControl.Dispose();
		}

		#endregion

		#region WoWBenchController Members

		/// <summary>
		/// Gets the WoWBench folder setting.
		/// </summary>
		internal string WoWBenchPath { private get; set; }

		/// <summary>
		/// Gets Runtime object.
		/// </summary>
		internal ILuaRuntime Runtime { get; private set; }

		#endregion

	}
}